How is genre (Pop, R&B, Country, etc) connected to sentiment? Are some genres more positive or negative than others? What types of values and connected themes are portrayed across different genres?
Here, we explore a set of lyrics from Metrolyrics.com to try to find interesting patterns.
First, let’s take a look at a word cloud of the lyrics used in each genre and the most common bigrams (pairs of consecutive words) by decade:
Part 1: Song Analysis:
Here, we examine the number of duplicate rows by lyrics. How many are repeats of songs by the same artist (possibly across more than once album)? 9605! This could have an effect on our most common words.
Additionally, there are 9671 total repeats by lyrics only. Subtract the two to find the number of songs covers (by another artist) in the dataset: 66
#repeats by both artist and stemmed words (lyrics)
repeats_same_artist <- dt_lyrics_1_a[(duplicated(dt_lyrics_1_a$stemmedwords)&duplicated(dt_lyrics_1_a$artist)), ]
#repeats by stemmed words alone
repeats_stemmed_words_only <- dt_lyrics_1_a[duplicated(dt_lyrics_1_a$stemmedwords), ]
repeats_across_artist <- dim(repeats_same_artist)[1]
repeats_across_all <- dim(repeats_stemmed_words_only)[1]
repeats <- data.frame(repeats_across_artist, repeats_across_all)
repeats
Let’s remove songs repeated across albums by the same artists for more accurate word counts:
To get a sense of some other differentiable characteristics of genres, remove words “love”, “time”, “baby”, “ill”, “ive”, “youre”, and “heart” because they show up the word cloud for every genre. So do “night” and “day”, but it’s interesting to see which genres have a larger emphasis on night vs which emphasize day. Also remove “chorus” because it is often used for labeling purposes in the dataset rather than as a lyric.
Let’s look at the word clouds again, this time with common words removed:
### Develop the server for the R Shiny app
#This shiny app visualizes summary of data and displays the data table itself.
# Define server logic required for ui ----
###changed to lyrics_2
server <- function(input, output) {
output$WC1 <- renderWordcloud2({
count(filter(word_tibble, id %in% which(dt_lyrics_2$genre == input$genre1)), word, sort = TRUE) %>%
slice(1:input$nwords1) %>%
wordcloud2(size=0.6, rotateRatio=0.2)
})
output$WC2 <- renderWordcloud2({
count(filter(word_tibble, id %in% which(dt_lyrics_2$genre == input$genre2)), word, sort = TRUE) %>%
slice(1:input$nwords2) %>%
wordcloud2(size=0.6, rotateRatio=0.2)
})
output$bigram1 <- renderPlotly({
year_start <- as.integer(substr(input$decade1, 1, 4))
dt_sub <- filter(dt_lyrics_2, year>=year_start) %>%
filter(year<(year_start+10))
lyric_bigrams <- dt_sub %>%
unnest_tokens(bigram, stemmedwords, token = "ngrams", n = 2)
bigram_counts <- lyric_bigrams %>%
separate(bigram, c("word1", "word2"), sep = " ") %>%
count(word1, word2, sort = TRUE)
combined_words <- apply(bigram_counts[c(1, 2)], 1, paste , collapse = " " )[1:input$topBigrams]
x_names <- factor(combined_words, levels = rev(combined_words))
plot_ly(
x = bigram_counts$n[1:input$topBigrams],
y = x_names,
name = "Bigram",
type = "bar",
orientation = 'h'
)
})
output$bigram2 <- renderPlotly({
year_start <- as.integer(substr(input$decade2, 1, 4))
dt_sub <- filter(dt_lyrics_2, year>=year_start) %>%
filter(year<(year_start+10))
lyric_bigrams <- dt_sub %>%
unnest_tokens(bigram, stemmedwords, token = "ngrams", n = 2)
bigram_counts <- lyric_bigrams %>%
separate(bigram, c("word1", "word2"), sep = " ") %>%
count(word1, word2, sort = TRUE)
combined_words <- apply(bigram_counts[c(1, 2)], 1, paste , collapse = " " )[1:input$topBigrams]
x_names <- factor(combined_words, levels = rev(combined_words))
plot_ly(
x = bigram_counts$n[1:input$topBigrams],
y = x_names,
name = "Bigram",
type = "bar",
orientation = 'h'
)
})
output$table <- DT::renderDataTable({
DT::datatable(dt_lyrics_2)
})
}
### Run the R Shiny app
shinyApp(ui, server)
NA
How many songs are in each genre?
counts <- table(dt_lyrics_1_a$genre)
barplot(counts, main = "# songs by genre", xlab = "genre", ylab = "# songs", col = "blue")

Let’s separate each song into individual lyrics using our original, full set of lyrics (including words like “love”). What are the most common words across the entire dataset?
tidy_lyrics_1_a %>%
arrange(desc(n)) %>%
mutate(word = factor(word, levels = rev(unique(word)))) %>%
top_n(25) %>%
ggplot(aes(word, n, fill="green")) +
geom_col(show.legend = FALSE) +
labs(x = "most common words", y = "number of occurences in dataset ") +
ggtitle("Most common words across dataset") +
coord_flip()

Now, we can see trends in the data!
Love is the most common word in every genre except Metal (where it still ranks highly, but is eclipsed by “time” and “life”). In Hip-Hop, “love” is closely followed in counts by “shit” (which is uniquely high-ranking in Hip-Hop).
lyrics_words_genre %>%
arrange(desc(n)) %>%
mutate(word = factor(word, levels = rev(unique(word)))) %>%
group_by(genre) %>%
top_n(12) %>%
ungroup() %>%
ggplot(aes(word, n, fill = genre)) +
geom_col(show.legend = FALSE) +
labs(x = "most common words", y = "number of occurences in genre ") +
facet_wrap(~genre, ncol = 2, scales = "free") +
coord_flip()
Selecting by n

Let’s take a closer look at bigrams. Which are the most common?
# look at most common bigrams by genre
bigram_counts_genre %>%
arrange(desc(n)) %>%
mutate(word = factor(bigram, levels = rev(unique(bigram)))) %>%
group_by(genre) %>%
top_n(12) %>%
ungroup() %>%
ggplot(aes(word, n, fill = genre)) +
geom_col(show.legend = FALSE) +
labs(x = "most common bigrams", y = "number of occurences in genre ") +
ggtitle("Most common bigrams by genre") +
facet_wrap(~genre, ncol = 2, scales = "free") +
coord_flip()
Let’s see what percentage of each genre is represented by the lyric “home”:
#save for all calculations; # bigrams total by genre
bigram_counts <- table(lyric_bigrams$genre)
#home
lyric_bigrams_home <- filter(bigrams,((word1 == "home")|(word2 == "home")))
bigram_counts_home <- table(lyric_bigrams_home$genre)
barplot(bigram_counts_home/bigram_counts, main = "percentage home counts by genre", xlab = "genre", ylab = "% lyrics", col = "blue")
We see that Indie, Country, and R&B have the highest percentage of “home” bigrams, followed by Folk, Jazz, and Rock. Home is a concept that can be tied to having a place of one’s own, often from a comfort standpoint. Could this be a reflection of trying to resonate with a culture valuing commitment and comfort?
How about “dream”?
lyric_bigrams_dream <- filter(bigrams,((word1 == "dream")|(word2 == "dream")))
bigram_counts_dream <- table(lyric_bigrams_dream$genre)
barplot(bigram_counts_dream/bigram_counts, main = "percentage dream counts by genre", xlab = "genre", ylab = "% lyrics", col = "blue")
Here the clear standouts are Jazz with over 1.4% of bigrams including “dream”, and Hip-Hop which mentions “dream” less frequently than Jazz does by a factor of 7! “dream” can be connected to abstract (as opposed to concrete) goals or episodes that occur outside reality. Could it be that Jazz is more about imagination and the hypothetical, while Hip-Hop is more about the real and concrete?
Let’s see “day” and “night” as a comparison:
#day
lyric_bigrams_day <- filter(bigrams,((word1 == "day")|(word2 == "day")))
bigram_counts_day <- table(lyric_bigrams_day$genre)
#night
lyric_bigrams_night <- filter(bigrams,((word1 == "night")|(word2 == "night")))
bigram_counts_night <- table(lyric_bigrams_night$genre)
#graph day v night
df_temporal <- rbind(bigram_counts_day/bigram_counts, bigram_counts_night/bigram_counts)
barplot(df_temporal, main = "percentage day vs night counts by genre", xlab = "genre", ylab = "% lyrics", col=c("lightblue","darkblue"), legend = c("day", "night"), beside = TRUE)
We can see that “day” is a more frequent theme than “night” in all genres in this dataset, with the exception of Electronic. Electronic music is often listened to at night, in dark spaces where listeners are equipped with fluorescent accessories. This is one hypothesis as to why Electronic music explicitly mentions night more frequently than day.
How about gendered words? Let’s look specifically at “boy” vs “girl”:
#boy
lyric_bigrams_boy <- filter(bigrams,((word1 == "boy")|(word2 == "boy")))
bigram_counts_boy <- table(lyric_bigrams_boy$genre)
#girl
lyric_bigrams_girl <- filter(bigrams,((word1 == "girl")|(word2 == "girl")))
bigram_counts_girl <- table(lyric_bigrams_girl$genre)
#graph boy v girl
df_gender <- rbind(bigram_counts_boy/bigram_counts, bigram_counts_girl/bigram_counts)
barplot(df_gender, main = "percentage boy vs girl counts by genre", xlab = "genre", ylab = "% lyrics", col=c("black","red"), legend = c("boy", "girl"), beside = TRUE)
This is the most stark comparison yet - it seems that in all genres, “girl” is mentioned more explictly than “boy”, and in the case of Hip-Hop, Pop, and R&B, “girl” is mentioned more than 2x as frequently as “boy”!
For fun, let’s throw “love”" in the mix:
#love
lyric_bigrams_love <- filter(bigrams,((word1 == "love")|(word2 == "love")))
bigram_counts_love <- table(lyric_bigrams_love$genre)
#graph boy v girl v love
df_gender_love <-rbind(bigram_counts_boy/bigram_counts, bigram_counts_girl/bigram_counts, bigram_counts_love/bigram_counts)
barplot(df_gender_love, main = "percentage boy vs girl vs love counts by genre", xlab = "genre", ylab = "% lyrics", col=c("black","red", "purple"), legend = c("boy", "girl", "love"), beside = TRUE)
We can see that Hip-Hop has the smallest gap between counts of “love” and “girl”, and that Jazz has an unusually high gap between “love” and “girl” compared to other genres. This is in line with the hypothesis that imagination or an ethereal state is more associated with Jazz, and reality/concreteness with Hip-Hop: girls are objectively tangible, while love is not.
Let’s do a sentiment analysis to see how negative or positive each genre is:
We see that the most positive genres (using the bing sentiment database) are Jazz (our potentially imaginitive and abstract genre), R&B, Pop, and Country. The most negative are Metal (see the word clouds from earlier - that’s a lot of death!) and Hip-Hop (our potentially realist category).
positive_freqs %>%
arrange(desc(percent)) %>%
mutate(word = factor(genre, levels = rev(unique(genre)))) %>%
#top_n(25) %>%
ggplot(aes(genre, percent, color="blue")) +
geom_col(show.legend = FALSE) +
labs(x = "genre", y = "percent positivity") +
ggtitle("How positive is the genre?")+
coord_flip()
What is the breakdown of sentiment by genre? We see that some genres (Jazz, R&B) have a more balanced positive v negative measure. In general, a surprising find is that anger and trust seem to occur in roughly similar frequencies within a given genre.
#code adapted from https://www.datacamp.com/community/tutorials/sentiment-analysis-R
nrc_word_counts %>%
group_by(genre) %>%
top_n(10) %>%
ungroup() %>%
mutate(sentiment = reorder(sentiment, nn)) %>%
#mutate(word = reorder(word, nn)) %>%
ggplot(aes(sentiment, nn, fill = genre)) +
geom_col(show.legend = FALSE) +
facet_wrap(~genre, scales = "free_y") +
labs(y = "sentiment",
x = "# counts of sentiment") +
ggtitle("Sentiment Breakdown by Genre") +
coord_flip()
References:
“Chengliang Tang, Arpita Shah, Yujie Wang and Tian Zheng” “lyrics_filter.csv” is a filtered corpus of 380,000+ song lyrics from from MetroLyrics. You can read more about it on Kaggle.
“info_artist.csv” provides the background information of all the artistis. These information are scraped from LyricsFreak.
The sentiment analysis makes use of the NRC Emotion and Sentiment Analysis, created by Saif M. Mohammad and Peter D. Turney at the National Research Council Canada. http://saifmohammad.com/WebPages/lexicons.html
Bing lexicon from https://www.cs.uic.edu/~liub/FBS/sentiment-analysis.html
Photo by Spencer Imbrock on Unsplash: https://unsplash.com/photos/JAHdPHMoaEA
Code snippets adapted from https://paldhous.github.io/NICAR/2019/r-text-analysis.html, https://www.tidytextmining.com/, and https://www.datacamp.com/community/tutorials/sentiment-analysis-R
LS0tCnRpdGxlOiAiRGF0YSBTdG9yeTogVGhlIFdvcmRzIFdlIFNpbmciCmF1dGhvcjogIkFzaGxleSBDdWx2ZXIiCm91dHB1dDogaHRtbF9ub3RlYm9vawpydW50aW1lOiBzaGlueQotLS0KCj4jKipEYXRhIFN0b3J5OiBUaGUgV29yZHMgV2UgU2luZyoqCj4jKipIb3cgYXJlIGdlbnJlcyBvZiBtdXNpYyBjaGFyYWN0ZXJpemVkIGJ5IGx5cmljcz8gQXJlIHNvbWUgbW9yZSBwb3NpdGl2ZSB0aGFuIG90aGVycz8qKgo8Y2VudGVyPkJ5IEFzaGxleSBDdWx2ZXI8L2NlbnRlcj4gIAohW211c2ljXSguLi9maWdzL211c2ljLmpwZykgCgo8Zm9udCBzaXplPTM+Ck11c2ljIGlzIGFuIGV4cHJlc3Npb24gb2YgY3VsdHVyZS4gTHlyaWNzIGFyZSBwb2V0cnkgc2V0IHRvIG11c2ljIC0gdGhleSBhY3QgYXMgYSBjb25kdWl0IHRvIGNvbm5lY3Qgd2l0aCBvdGhlcnMsIHRlbGwgYSBzdG9yeSwgYW5kIHJlc29uYXRlIHdpdGggYSBwYXJ0aWN1bGFyIGF1ZGllbmNlLgoKSG93IGlzIGdlbnJlIChQb3AsIFImQiwgQ291bnRyeSwgZXRjKSBjb25uZWN0ZWQgdG8gc2VudGltZW50PyBBcmUgc29tZSBnZW5yZXMgbW9yZSBwb3NpdGl2ZSBvciBuZWdhdGl2ZSB0aGFuIG90aGVycz8gV2hhdCB0eXBlcyBvZiB2YWx1ZXMgYW5kIGNvbm5lY3RlZCB0aGVtZXMgYXJlIHBvcnRyYXllZCBhY3Jvc3MgZGlmZmVyZW50IGdlbnJlcz8KCkhlcmUsIHdlIGV4cGxvcmUgYSBzZXQgb2YgbHlyaWNzIGZyb20gTWV0cm9seXJpY3MuY29tIHRvIHRyeSB0byBmaW5kIGludGVyZXN0aW5nIHBhdHRlcm5zLiAKCkZpcnN0LCBsZXQncyB0YWtlIGEgbG9vayBhdCBhIHdvcmQgY2xvdWQgb2YgdGhlIGx5cmljcyB1c2VkIGluIGVhY2ggZ2VucmUgYW5kIHRoZSBtb3N0IGNvbW1vbiBiaWdyYW1zIChwYWlycyBvZiBjb25zZWN1dGl2ZSB3b3JkcykgYnkgZGVjYWRlOgpgYGB7ciBsb2FkIGxpYnJhcmllcywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBMb2FkIGFsbCB0aGUgcmVxdWlyZWQgbGlicmFyaWVzCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHRpZHl0ZXh0KQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShEVCkKbGlicmFyeSh0bSkKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeSh3b3JkY2xvdWQyKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShuZ3JhbSkKbGlicmFyeShzaGlueSkgCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh0ZXh0ZGF0YSkKYGBgCgpgYGB7cix3YXJuaW5nPUZBTFNFLGVycm9yPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRX0KIyMjIExvYWQgdGhlIHByb2Nlc3NlZCBseXJpY3MgZGF0YSBhbG9uZyB3aXRoIGFydGlzdCBpbmZvcm1hdGlvbgoKIyBsb2FkIGx5cmljcyBkYXRhCmxvYWQoJy4uL291dHB1dC9wcm9jZXNzZWRfbHlyaWNzLlJEYXRhJykgCgojIGxvYWQgYXJ0aXN0IGluZm9ybWF0aW9uCiNkdF9hcnRpc3QgPC0gZnJlYWQoJ2RhdGEvYXJ0aXN0cy5jc3YnKSAKYGBgCgpgYGB7ciwgd2FybmluZz1GQUxTRSxlcnJvcj1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CiMjIyBQcmVwYXJhdGlvbnMgZm9yIHZpc3VhbGl6YXRpb24KbHlyaWNzX2xpc3QgPC0gYygiRm9sayIsICJSJkIiLCAiRWxlY3Ryb25pYyIsICJKYXp6IiwgIkluZGllIiwgIkNvdW50cnkiLCAiUm9jayIsICJNZXRhbCIsICJQb3AiLCAiSGlwLUhvcCIsICJPdGhlciIpCnRpbWVfbGlzdCA8LSBjKCIxOTcwcyIsICIxOTgwcyIsICIxOTkwcyIsICIyMDAwcyIsICIyMDEwcyIpCmNvcnB1cyA8LSBWQ29ycHVzKFZlY3RvclNvdXJjZShkdF9seXJpY3Mkc3RlbW1lZHdvcmRzKSkKd29yZF90aWJibGUgPC0gdGlkeShjb3JwdXMpICU+JQogIHNlbGVjdCh0ZXh0KSAlPiUKICBtdXRhdGUoaWQgPSByb3dfbnVtYmVyKCkpICU+JQogIHVubmVzdF90b2tlbnMod29yZCwgdGV4dCkKYGBgCgpgYGB7ciwgd2FybmluZz1GQUxTRSxlcnJvcj1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CiMjI0FkZGl0aW9uYWwgdGV4dCBjbGVhbmluZwphZGRsX3N0b3B3b3JkcyA8LSBjKCJuaWdnYXMiLCAibmlnZ2F6IikgI3JlbW92ZSByYWNpYWxseSBjaGFyZ2VkIHdvcmRzCmR0X2x5cmljc18xX2EgPC1kdF9seXJpY3MgICNjcmVhdGUgbmV3IHRpYmJsZSB0byByZW1vdmUgYWRkaXRpb25hbCBzdG9wd29yZHMKCnggPC0gZHRfbHlyaWNzXzFfYSRzdGVtbWVkd29yZHMgICAgICAgI3N0ZW1tZWR3b3JkcyBkYXRhCnggIDwtICByZW1vdmVXb3Jkcyh4LGFkZGxfc3RvcHdvcmRzKSAgICAgI1JlbW92ZSBhZGRpdGlvbmFsIHN0b3B3b3JkcwpkdF9seXJpY3NfMV9hJHN0ZW1tZWR3b3JkcyA8LSB4ICAgICAgICAjY29ycmVjdCBjb2x1bW4gYnkgbWF0Y2hpbmcgc3RlbW1lZHdvcmRzIGNvbHVtbiB0byBtYXRjaCB4IApgYGAKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLGVycm9yPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRX0KIyMjIFNwZWNpZnkgdGhlIHVzZXIgaW50ZXJmYWNlIGZvciB0aGUgUiBTaGlueSBhcHAKCiMgRGVmaW5lIFVJIGZvciBhcHAgdGhhdCBkcmF3cyBhIGhpc3RvZ3JhbSAtLS0tCnVpIDwtIG5hdmJhclBhZ2Uoc3Ryb25nKCJMeXJpY3MgQW5hbHlzaXMiKSwKICB0YWJQYW5lbCgiT3ZlcnZpZXciLAogICAgdGl0bGVQYW5lbCgiTW9zdCBmcmVxdWVudCB3b3JkcyIpLAogICAgIyBTaWRlYmFyIGxheW91dCB3aXRoIGlucHV0IGFuZCBvdXRwdXQgZGVmaW5pdGlvbnMgLS0tLQogICAgc2lkZWJhckxheW91dCgKICAgICAgIyBTaWRlYmFyIHBhbmVsIGZvciBpbnB1dHMgLS0tLQogICAgICBzaWRlYmFyUGFuZWwoCiAgICAgICAgc2xpZGVySW5wdXQoaW5wdXRJZCA9ICJud29yZHMxIiwKICAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICJOdW1iZXIgb2YgdGVybXMgaW4gdGhlIGZpcnN0IHdvcmQgY2xvdWQ6IiwKICAgICAgICAgICAgICAgICAgICBtaW4gPSA1LCBtYXggPSAxMDAsIHZhbHVlID0gNTApLAogICAgICAgIHNlbGVjdElucHV0KCdnZW5yZTEnLCAnR2VucmUgb2YgdGhlIGZpcnN0IHdvcmQgY2xvdWQnLCAKICAgICAgICAgICAgICAgICAgICBseXJpY3NfbGlzdCwgc2VsZWN0ZWQ9J0ZvbGsnKQogICAgKSwKICAgICMgTWFpbiBwYW5lbCBmb3IgZGlzcGxheWluZyBvdXRwdXRzIC0tLS0KICAgIG1haW5QYW5lbCgKICAgICAgd29yZGNsb3VkMk91dHB1dChvdXRwdXRJZCA9ICJXQzEiLCBoZWlnaHQgPSAiMzAwIikKICAgICkKICApLAogIGhyKCksCiAgc2lkZWJhckxheW91dCgKICAgICAgIyBTaWRlYmFyIHBhbmVsIGZvciBpbnB1dHMgLS0tLQogICAgICBzaWRlYmFyUGFuZWwoCiAgICAgICAgc2xpZGVySW5wdXQoaW5wdXRJZCA9ICJud29yZHMyIiwKICAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICJOdW1iZXIgb2YgdGVybXMgaW4gdGhlIHNlY29uZCB3b3JkIGNsb3VkOiIsCiAgICAgICAgICAgICAgICAgICAgbWluID0gNSwgbWF4ID0gMTAwLCB2YWx1ZSA9IDUwKSwKICAgICAgICBzZWxlY3RJbnB1dCgnZ2VucmUyJywgJ0dlbnJlIG9mIHRoZSBzZWNvbmQgd29yZCBjbG91ZCcsIAogICAgICAgICAgICAgICAgICAgIGx5cmljc19saXN0LCBzZWxlY3RlZD0nTWV0YWwnKQogICAgKSwKICAgICMgTWFpbiBwYW5lbCBmb3IgZGlzcGxheWluZyBvdXRwdXRzIC0tLS0KICAgIG1haW5QYW5lbCgKICAgICAgd29yZGNsb3VkMk91dHB1dChvdXRwdXRJZCA9ICJXQzIiLCBoZWlnaHQgPSAiMzAwIikKICAgICkKICApCiAgICAgICAgICAgKSwKICB0YWJQYW5lbCgiVGltZSBWYXJpYXRpb24iLAogICAgICAgICAgICMgU2lkZWJhciBsYXlvdXQgd2l0aCBpbnB1dCBhbmQgb3V0cHV0IGRlZmluaXRpb25zIC0tLS0KICAgICAgICAgIHNpZGViYXJMYXlvdXQoCiAgICAgICAgICAgICMgU2lkZWJhciBwYW5lbCBmb3IgaW5wdXRzIC0tLS0KICAgICAgICAgICAgc2lkZWJhclBhbmVsKAogICAgICAgICAgICAgIHNlbGVjdElucHV0KCdkZWNhZGUxJywgJ1NlbGVjdGVkIGRlY2FkZSBmb3IgdGhlIGZpcnN0IHBsb3Q6JywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZV9saXN0LCBzZWxlY3RlZD0nMTk3MHMnKSwKICAgICAgICAgICAgICBzZWxlY3RJbnB1dCgnZGVjYWRlMicsICdTZWxlY3RlZCBkZWNhZGUgZm9yIHRoZSBzZWNvbmQgcGxvdDonLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lX2xpc3QsIHNlbGVjdGVkPScxOTgwcycpLAogICAgICAgICAgICAgIG51bWVyaWNJbnB1dChpbnB1dElkID0gInRvcEJpZ3JhbXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICJOdW1iZXIgb2YgdG9wIHBhaXJzIHRvIHZpZXc6IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4ID0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gMTApCiAgICAgIAogICAgICAgICAgKSwKICAgICAgICAgICMgTWFpbiBwYW5lbCBmb3IgZGlzcGxheWluZyBvdXRwdXRzIC0tLS0KICAgICAgICAgIG1haW5QYW5lbCgKICAgICAgICAgICAgZmx1aWRSb3coCiAgICAgICAgICAgICAgY29sdW1uKDUsCiAgICAgICAgICAgICAgICAgICAgIHBsb3RseU91dHB1dCgiYmlncmFtMSIpKSwKICAgICAgICAgICAgICBjb2x1bW4oNSwKICAgICAgICAgICAgICAgICAgICAgcGxvdGx5T3V0cHV0KCJiaWdyYW0yIikpCiAgICAgICAgICAgICkKICAgICAgICAgICkKICAgICAgICApCiAgICAgICAgICAgKSwKICB0YWJQYW5lbCgiRGF0YSIsIAogICAgICAgICAgIERUOjpkYXRhVGFibGVPdXRwdXQoInRhYmxlIikpCikKYGBgCgpgYGB7ciwgd2FybmluZz1GQUxTRSxlcnJvcj1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CiMjIyBEZXZlbG9wIHRoZSBzZXJ2ZXIgZm9yIHRoZSBSIFNoaW55IGFwcAojVGhpcyBzaGlueSBhcHAgdmlzdWFsaXplcyBzdW1tYXJ5IG9mIGRhdGEgYW5kIGRpc3BsYXlzIHRoZSBkYXRhIHRhYmxlIGl0c2VsZi4KCiMgRGVmaW5lIHNlcnZlciBsb2dpYyByZXF1aXJlZCBmb3IgdWkgLS0tLQojIyNjaGFuZ2VkIHRvIGx5cmljc18yCnNlcnZlciA8LSBmdW5jdGlvbihpbnB1dCwgb3V0cHV0KSB7CiAgb3V0cHV0JFdDMSA8LSByZW5kZXJXb3JkY2xvdWQyKHsKICAgIGNvdW50KGZpbHRlcih3b3JkX3RpYmJsZSwgaWQgJWluJSB3aGljaChkdF9seXJpY3NfMV9hJGdlbnJlID09IGlucHV0JGdlbnJlMSkpLCB3b3JkLCBzb3J0ID0gVFJVRSkgJT4lCiAgICAgIHNsaWNlKDE6aW5wdXQkbndvcmRzMSkgJT4lCiAgICAgIHdvcmRjbG91ZDIoc2l6ZT0wLjYsIHJvdGF0ZVJhdGlvPTAuMikKICB9KQogIG91dHB1dCRXQzIgPC0gcmVuZGVyV29yZGNsb3VkMih7CiAgICBjb3VudChmaWx0ZXIod29yZF90aWJibGUsIGlkICVpbiUgd2hpY2goZHRfbHlyaWNzXzFfYSRnZW5yZSA9PSBpbnB1dCRnZW5yZTIpKSwgd29yZCwgc29ydCA9IFRSVUUpICU+JQogICAgICBzbGljZSgxOmlucHV0JG53b3JkczIpICU+JQogICAgICB3b3JkY2xvdWQyKHNpemU9MC42LCByb3RhdGVSYXRpbz0wLjIpCiAgfSkKICBvdXRwdXQkYmlncmFtMSA8LSByZW5kZXJQbG90bHkoewogICAgeWVhcl9zdGFydCA8LSBhcy5pbnRlZ2VyKHN1YnN0cihpbnB1dCRkZWNhZGUxLCAxLCA0KSkKICAgIGR0X3N1YiA8LSBmaWx0ZXIoZHRfbHlyaWNzXzFfYSwgeWVhcj49eWVhcl9zdGFydCkgJT4lCiAgICAgIGZpbHRlcih5ZWFyPCh5ZWFyX3N0YXJ0KzEwKSkKICAgIGx5cmljX2JpZ3JhbXMgPC0gZHRfc3ViICU+JQogICAgICB1bm5lc3RfdG9rZW5zKGJpZ3JhbSwgc3RlbW1lZHdvcmRzLCB0b2tlbiA9ICJuZ3JhbXMiLCBuID0gMikKICAgIGJpZ3JhbV9jb3VudHMgPC0gbHlyaWNfYmlncmFtcyAlPiUKICAgICAgc2VwYXJhdGUoYmlncmFtLCBjKCJ3b3JkMSIsICJ3b3JkMiIpLCBzZXAgPSAiICIpICU+JQogICAgICBjb3VudCh3b3JkMSwgd29yZDIsIHNvcnQgPSBUUlVFKQogICAgY29tYmluZWRfd29yZHMgPC0gYXBwbHkoYmlncmFtX2NvdW50c1tjKDEsIDIpXSwgMSwgcGFzdGUgLCBjb2xsYXBzZSA9ICIgIiApWzE6aW5wdXQkdG9wQmlncmFtc10KICAgIHhfbmFtZXMgPC0gZmFjdG9yKGNvbWJpbmVkX3dvcmRzLCBsZXZlbHMgPSByZXYoY29tYmluZWRfd29yZHMpKQogICAgcGxvdF9seSgKICAgICAgeCA9IGJpZ3JhbV9jb3VudHMkblsxOmlucHV0JHRvcEJpZ3JhbXNdLAogICAgICB5ID0geF9uYW1lcywKICAgICAgbmFtZSA9ICJCaWdyYW0iLAogICAgICB0eXBlID0gImJhciIsCiAgICAgIG9yaWVudGF0aW9uID0gJ2gnCiAgICApCiAgfSkKICBvdXRwdXQkYmlncmFtMiA8LSByZW5kZXJQbG90bHkoewogICAgeWVhcl9zdGFydCA8LSBhcy5pbnRlZ2VyKHN1YnN0cihpbnB1dCRkZWNhZGUyLCAxLCA0KSkKICAgIGR0X3N1YiA8LSBmaWx0ZXIoZHRfbHlyaWNzXzFfYSwgeWVhcj49eWVhcl9zdGFydCkgJT4lCiAgICAgIGZpbHRlcih5ZWFyPCh5ZWFyX3N0YXJ0KzEwKSkKICAgIGx5cmljX2JpZ3JhbXMgPC0gZHRfc3ViICU+JQogICAgICB1bm5lc3RfdG9rZW5zKGJpZ3JhbSwgc3RlbW1lZHdvcmRzLCB0b2tlbiA9ICJuZ3JhbXMiLCBuID0gMikKICAgIGJpZ3JhbV9jb3VudHMgPC0gbHlyaWNfYmlncmFtcyAlPiUKICAgICAgc2VwYXJhdGUoYmlncmFtLCBjKCJ3b3JkMSIsICJ3b3JkMiIpLCBzZXAgPSAiICIpICU+JQogICAgICBjb3VudCh3b3JkMSwgd29yZDIsIHNvcnQgPSBUUlVFKQogICAgY29tYmluZWRfd29yZHMgPC0gYXBwbHkoYmlncmFtX2NvdW50c1tjKDEsIDIpXSwgMSwgcGFzdGUgLCBjb2xsYXBzZSA9ICIgIiApWzE6aW5wdXQkdG9wQmlncmFtc10KICAgIHhfbmFtZXMgPC0gZmFjdG9yKGNvbWJpbmVkX3dvcmRzLCBsZXZlbHMgPSByZXYoY29tYmluZWRfd29yZHMpKQogICAgcGxvdF9seSgKICAgICAgeCA9IGJpZ3JhbV9jb3VudHMkblsxOmlucHV0JHRvcEJpZ3JhbXNdLAogICAgICB5ID0geF9uYW1lcywKICAgICAgbmFtZSA9ICJCaWdyYW0iLAogICAgICB0eXBlID0gImJhciIsCiAgICAgIG9yaWVudGF0aW9uID0gJ2gnCiAgICApCiAgfSkKICBvdXRwdXQkdGFibGUgPC0gRFQ6OnJlbmRlckRhdGFUYWJsZSh7CiAgICBEVDo6ZGF0YXRhYmxlKGR0X2x5cmljc18xX2EpCiAgfSkKfQpgYGAKCiMjIyBSdW4gdGhlIFIgU2hpbnkgYXBwCgpgYGB7ciBzaGlueV8yIGFwcCwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0Kc2hpbnlBcHAodWksIHNlcnZlcikKYGBgCgpJbW1lZGlhdGVseSwgYSBmZXcgb2JzZXJ2YXRpb25zIGp1bXAgb3V0OiBsb3ZlLCB0aW1lLCBuaWdodCwgYW5kIGRheSwgYXJlIHByZXR0eSBjb21tb24gdGhlbWVzLiBBZGRpdGlvbmFsbHksIHdlIGNhbiBzZWUgdGhhdCBjb25qdW5jdGlvbnMgYWRkcmVzc2luZyBwZXJzb25ob29kICgieW91J3JlIiBhbmQgIkknbGwiKSBhcmUgcHJldHR5IGZyZXF1ZW50LgoKCiMjUGFydCAxOiBTb25nIEFuYWx5c2lzOiAKCkhlcmUsIHdlIGV4YW1pbmUgdGhlIG51bWJlciBvZiBkdXBsaWNhdGUgcm93cyBieSBseXJpY3MuIEhvdyBtYW55IGFyZSByZXBlYXRzIG9mIHNvbmdzIGJ5IHRoZSBzYW1lIGFydGlzdCAocG9zc2libHkgYWNyb3NzIG1vcmUgdGhhbiBvbmNlIGFsYnVtKT8gOTYwNSEgVGhpcyBjb3VsZCBoYXZlIGFuIGVmZmVjdCBvbiBvdXIgbW9zdCBjb21tb24gd29yZHMuCgpBZGRpdGlvbmFsbHksIHRoZXJlIGFyZSA5NjcxIHRvdGFsIHJlcGVhdHMgYnkgbHlyaWNzIG9ubHkuIFN1YnRyYWN0IHRoZSB0d28gdG8gZmluZCB0aGUgbnVtYmVyIG9mIHNvbmdzIGNvdmVycyAoYnkgYW5vdGhlciBhcnRpc3QpIGluIHRoZSBkYXRhc2V0OiA2NgpgYGB7cix3YXJuaW5nPUZBTFNFLGVycm9yPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CiNyZXBlYXRzIGJ5IGJvdGggYXJ0aXN0IGFuZCBzdGVtbWVkIHdvcmRzIChseXJpY3MpCnJlcGVhdHNfc2FtZV9hcnRpc3QgPC0gZHRfbHlyaWNzXzFfYVsoZHVwbGljYXRlZChkdF9seXJpY3NfMV9hJHN0ZW1tZWR3b3JkcykmZHVwbGljYXRlZChkdF9seXJpY3NfMV9hJGFydGlzdCkpLCBdCgojcmVwZWF0cyBieSBzdGVtbWVkIHdvcmRzIGFsb25lIApyZXBlYXRzX3N0ZW1tZWRfd29yZHNfb25seSA8LSBkdF9seXJpY3NfMV9hW2R1cGxpY2F0ZWQoZHRfbHlyaWNzXzFfYSRzdGVtbWVkd29yZHMpLCBdCgpyZXBlYXRzX2Fjcm9zc19hcnRpc3QgPC0gZGltKHJlcGVhdHNfc2FtZV9hcnRpc3QpWzFdCnJlcGVhdHNfYWNyb3NzX2FsbCA8LSBkaW0ocmVwZWF0c19zdGVtbWVkX3dvcmRzX29ubHkpWzFdCgpyZXBlYXRzIDwtIGRhdGEuZnJhbWUocmVwZWF0c19hY3Jvc3NfYXJ0aXN0LCByZXBlYXRzX2Fjcm9zc19hbGwpCnJlcGVhdHMKYGBgCgpMZXQncyByZW1vdmUgc29uZ3MgcmVwZWF0ZWQgYWNyb3NzIGFsYnVtcyBieSB0aGUgc2FtZSBhcnRpc3RzIGZvciBtb3JlIGFjY3VyYXRlIHdvcmQgY291bnRzOgpgYGB7ciwgd2FybmluZz1GQUxTRSxlcnJvcj1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CmR0X2x5cmljc18xX2EgJT4lIGRpc3RpbmN0KGFydGlzdCwgc3RlbW1lZHdvcmRzLCAua2VlcF9hbGwgPSBUUlVFKQpgYGAKVG8gZ2V0IGEgc2Vuc2Ugb2Ygc29tZSBvdGhlciBkaWZmZXJlbnRpYWJsZSBjaGFyYWN0ZXJpc3RpY3Mgb2YgZ2VucmVzLCByZW1vdmUgd29yZHMgImxvdmUiLCAidGltZSIsICJiYWJ5IiwgImlsbCIsICJpdmUiLCAieW91cmUiLCBhbmQgImhlYXJ0IiBiZWNhdXNlIHRoZXkgc2hvdyB1cCB0aGUgd29yZCBjbG91ZCBmb3IgZXZlcnkgZ2VucmUuIFNvIGRvICJuaWdodCIgYW5kICJkYXkiLCBidXQgaXQncyBpbnRlcmVzdGluZyB0byBzZWUgd2hpY2ggZ2VucmVzIGhhdmUgYSBsYXJnZXIgZW1waGFzaXMgb24gbmlnaHQgdnMgd2hpY2ggZW1waGFzaXplIGRheS4gQWxzbyByZW1vdmUgImNob3J1cyIgYmVjYXVzZSBpdCBpcyBvZnRlbiB1c2VkIGZvciBsYWJlbGluZyBwdXJwb3NlcyBpbiB0aGUgZGF0YXNldCByYXRoZXIgdGhhbiBhcyBhIGx5cmljLgoKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLGVycm9yPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRX0KI2NvZGUgZGlyZWN0aW9uIGZvciByZW1vdmluZyBhZGRpdGlvbmFsIHdvcmRzIGZyb20gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNDA5MDExMDAvcmVtb3ZlLWNlcnRhaW4td29yZHMtaW4tc3RyaW5nLWZyb20tY29sdW1uLWluLWRhdGFmcmFtZS1pbi1yCgpjb21tb25fd29yZHMgPC0gYygibG92ZSIsICJ0aW1lIiwgImJhYnkiLCAiaWxsIiwgIml2ZSIsICJ5b3VyZSIsICJoZWFydCIsICJjaG9ydXMiKQpkdF9seXJpY3NfMiA8LSBkdF9seXJpY3NfMV9hCgp5IDwtIGR0X2x5cmljc18yJHN0ZW1tZWR3b3Jkcwp5IDwtIHJlbW92ZVdvcmRzKHksIGNvbW1vbl93b3JkcykgICAgICNSZW1vdmUgYWRkaXRpb25hbCBzdG9wd29yZHMKZHRfbHlyaWNzXzIkc3RlbW1lZHdvcmRzIDwtIHkgICAgICAgICAjY29ycmVjdCBjb2x1bW4gYnkgbWF0Y2hpbmcgc3RlbW1lZHdvcmRzIGNvbHVtbiB0byBtYXRjaCB5CmBgYAoKTGV0J3MgbG9vayBhdCB0aGUgd29yZCBjbG91ZHMgYWdhaW4sIHRoaXMgdGltZSB3aXRoIGNvbW1vbiB3b3JkcyByZW1vdmVkOgoKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLGVycm9yPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRX0KIyMjIFByZXBhcmF0aW9ucyBmb3IgdmlzdWFsaXphdGlvbiB1c2luZyBtb3JlIGFjY3VyYXRlIGRhdGEgYnJlYWtkb3duCmx5cmljc19saXN0IDwtIGMoIkZvbGsiLCAiUiZCIiwgIkVsZWN0cm9uaWMiLCAiSmF6eiIsICJJbmRpZSIsICJDb3VudHJ5IiwgIlJvY2siLCAiTWV0YWwiLCAiUG9wIiwgIkhpcC1Ib3AiLCAiT3RoZXIiKQp0aW1lX2xpc3QgPC0gYygiMTk3MHMiLCAiMTk4MHMiLCAiMTk5MHMiLCAiMjAwMHMiLCAiMjAxMHMiKQpjb3JwdXMgPC0gVkNvcnB1cyhWZWN0b3JTb3VyY2UoZHRfbHlyaWNzXzIkc3RlbW1lZHdvcmRzKSkKd29yZF90aWJibGUgPC0gdGlkeShjb3JwdXMpICU+JQogIHNlbGVjdCh0ZXh0KSAlPiUKICBtdXRhdGUoaWQgPSByb3dfbnVtYmVyKCkpICU+JQogIHVubmVzdF90b2tlbnMod29yZCwgdGV4dCkKYGBgCgpgYGB7ciwgd2FybmluZz1GQUxTRSxlcnJvcj1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CiMjIyBTcGVjaWZ5IHRoZSB1c2VyIGludGVyZmFjZSBmb3IgdGhlIFIgU2hpbnkgYXBwCgojIERlZmluZSBVSSBmb3IgYXBwIHRoYXQgZHJhd3MgYSBoaXN0b2dyYW0gLS0tLQp1aSA8LSBuYXZiYXJQYWdlKHN0cm9uZygiTHlyaWNzIEFuYWx5c2lzIiksCiAgdGFiUGFuZWwoIk92ZXJ2aWV3IiwKICAgIHRpdGxlUGFuZWwoIk1vc3QgZnJlcXVlbnQgd29yZHMiKSwKICAgICMgU2lkZWJhciBsYXlvdXQgd2l0aCBpbnB1dCBhbmQgb3V0cHV0IGRlZmluaXRpb25zIC0tLS0KICAgIHNpZGViYXJMYXlvdXQoCiAgICAgICMgU2lkZWJhciBwYW5lbCBmb3IgaW5wdXRzIC0tLS0KICAgICAgc2lkZWJhclBhbmVsKAogICAgICAgIHNsaWRlcklucHV0KGlucHV0SWQgPSAibndvcmRzMSIsCiAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSAiTnVtYmVyIG9mIHRlcm1zIGluIHRoZSBmaXJzdCB3b3JkIGNsb3VkOiIsCiAgICAgICAgICAgICAgICAgICAgbWluID0gNSwgbWF4ID0gMTAwLCB2YWx1ZSA9IDUwKSwKICAgICAgICBzZWxlY3RJbnB1dCgnZ2VucmUxJywgJ0dlbnJlIG9mIHRoZSBmaXJzdCB3b3JkIGNsb3VkJywgCiAgICAgICAgICAgICAgICAgICAgbHlyaWNzX2xpc3QsIHNlbGVjdGVkPSdGb2xrJykKICAgICksCiAgICAjIE1haW4gcGFuZWwgZm9yIGRpc3BsYXlpbmcgb3V0cHV0cyAtLS0tCiAgICBtYWluUGFuZWwoCiAgICAgIHdvcmRjbG91ZDJPdXRwdXQob3V0cHV0SWQgPSAiV0MxIiwgaGVpZ2h0ID0gIjMwMCIpCiAgICApCiAgKSwKICBocigpLAogIHNpZGViYXJMYXlvdXQoCiAgICAgICMgU2lkZWJhciBwYW5lbCBmb3IgaW5wdXRzIC0tLS0KICAgICAgc2lkZWJhclBhbmVsKAogICAgICAgIHNsaWRlcklucHV0KGlucHV0SWQgPSAibndvcmRzMiIsCiAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSAiTnVtYmVyIG9mIHRlcm1zIGluIHRoZSBzZWNvbmQgd29yZCBjbG91ZDoiLAogICAgICAgICAgICAgICAgICAgIG1pbiA9IDUsIG1heCA9IDEwMCwgdmFsdWUgPSA1MCksCiAgICAgICAgc2VsZWN0SW5wdXQoJ2dlbnJlMicsICdHZW5yZSBvZiB0aGUgc2Vjb25kIHdvcmQgY2xvdWQnLCAKICAgICAgICAgICAgICAgICAgICBseXJpY3NfbGlzdCwgc2VsZWN0ZWQ9J01ldGFsJykKICAgICksCiAgICAjIE1haW4gcGFuZWwgZm9yIGRpc3BsYXlpbmcgb3V0cHV0cyAtLS0tCiAgICBtYWluUGFuZWwoCiAgICAgIHdvcmRjbG91ZDJPdXRwdXQob3V0cHV0SWQgPSAiV0MyIiwgaGVpZ2h0ID0gIjMwMCIpCiAgICApCiAgKQogICAgICAgICAgICksCiAgdGFiUGFuZWwoIlRpbWUgVmFyaWF0aW9uIiwKICAgICAgICAgICAjIFNpZGViYXIgbGF5b3V0IHdpdGggaW5wdXQgYW5kIG91dHB1dCBkZWZpbml0aW9ucyAtLS0tCiAgICAgICAgICBzaWRlYmFyTGF5b3V0KAogICAgICAgICAgICAjIFNpZGViYXIgcGFuZWwgZm9yIGlucHV0cyAtLS0tCiAgICAgICAgICAgIHNpZGViYXJQYW5lbCgKICAgICAgICAgICAgICBzZWxlY3RJbnB1dCgnZGVjYWRlMScsICdTZWxlY3RlZCBkZWNhZGUgZm9yIHRoZSBmaXJzdCBwbG90OicsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVfbGlzdCwgc2VsZWN0ZWQ9JzE5NzBzJyksCiAgICAgICAgICAgICAgc2VsZWN0SW5wdXQoJ2RlY2FkZTInLCAnU2VsZWN0ZWQgZGVjYWRlIGZvciB0aGUgc2Vjb25kIHBsb3Q6JywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZV9saXN0LCBzZWxlY3RlZD0nMTk4MHMnKSwKICAgICAgICAgICAgICBudW1lcmljSW5wdXQoaW5wdXRJZCA9ICJ0b3BCaWdyYW1zIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSAiTnVtYmVyIG9mIHRvcCBwYWlycyB0byB2aWV3OiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbiA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heCA9IDIwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IDEwKQogICAgICAKICAgICAgICAgICksCiAgICAgICAgICAjIE1haW4gcGFuZWwgZm9yIGRpc3BsYXlpbmcgb3V0cHV0cyAtLS0tCiAgICAgICAgICBtYWluUGFuZWwoCiAgICAgICAgICAgIGZsdWlkUm93KAogICAgICAgICAgICAgIGNvbHVtbig1LAogICAgICAgICAgICAgICAgICAgICBwbG90bHlPdXRwdXQoImJpZ3JhbTEiKSksCiAgICAgICAgICAgICAgY29sdW1uKDUsCiAgICAgICAgICAgICAgICAgICAgIHBsb3RseU91dHB1dCgiYmlncmFtMiIpKQogICAgICAgICAgICApCiAgICAgICAgICApCiAgICAgICAgKQogICAgICAgICAgICksCiAgdGFiUGFuZWwoIkRhdGEiLCAKICAgICAgICAgICBEVDo6ZGF0YVRhYmxlT3V0cHV0KCJ0YWJsZSIpKQopCmBgYAoKYGBge3J9CiMjIyBEZXZlbG9wIHRoZSBzZXJ2ZXIgZm9yIHRoZSBSIFNoaW55IGFwcAojVGhpcyBzaGlueSBhcHAgdmlzdWFsaXplcyBzdW1tYXJ5IG9mIGRhdGEgYW5kIGRpc3BsYXlzIHRoZSBkYXRhIHRhYmxlIGl0c2VsZi4KCiMgRGVmaW5lIHNlcnZlciBsb2dpYyByZXF1aXJlZCBmb3IgdWkgLS0tLQojIyNjaGFuZ2VkIHRvIGx5cmljc18yCgpzZXJ2ZXIgPC0gZnVuY3Rpb24oaW5wdXQsIG91dHB1dCkgewogIG91dHB1dCRXQzEgPC0gcmVuZGVyV29yZGNsb3VkMih7CiAgICBjb3VudChmaWx0ZXIod29yZF90aWJibGUsIGlkICVpbiUgd2hpY2goZHRfbHlyaWNzXzIkZ2VucmUgPT0gaW5wdXQkZ2VucmUxKSksIHdvcmQsIHNvcnQgPSBUUlVFKSAlPiUKICAgICAgc2xpY2UoMTppbnB1dCRud29yZHMxKSAlPiUKICAgICAgd29yZGNsb3VkMihzaXplPTAuNiwgcm90YXRlUmF0aW89MC4yKQogIH0pCiAgb3V0cHV0JFdDMiA8LSByZW5kZXJXb3JkY2xvdWQyKHsKICAgIGNvdW50KGZpbHRlcih3b3JkX3RpYmJsZSwgaWQgJWluJSB3aGljaChkdF9seXJpY3NfMiRnZW5yZSA9PSBpbnB1dCRnZW5yZTIpKSwgd29yZCwgc29ydCA9IFRSVUUpICU+JQogICAgICBzbGljZSgxOmlucHV0JG53b3JkczIpICU+JQogICAgICB3b3JkY2xvdWQyKHNpemU9MC42LCByb3RhdGVSYXRpbz0wLjIpCiAgfSkKICBvdXRwdXQkYmlncmFtMSA8LSByZW5kZXJQbG90bHkoewogICAgeWVhcl9zdGFydCA8LSBhcy5pbnRlZ2VyKHN1YnN0cihpbnB1dCRkZWNhZGUxLCAxLCA0KSkKICAgIGR0X3N1YiA8LSBmaWx0ZXIoZHRfbHlyaWNzXzIsIHllYXI+PXllYXJfc3RhcnQpICU+JQogICAgICBmaWx0ZXIoeWVhcjwoeWVhcl9zdGFydCsxMCkpCiAgICBseXJpY19iaWdyYW1zIDwtIGR0X3N1YiAlPiUKICAgICAgdW5uZXN0X3Rva2VucyhiaWdyYW0sIHN0ZW1tZWR3b3JkcywgdG9rZW4gPSAibmdyYW1zIiwgbiA9IDIpCiAgICBiaWdyYW1fY291bnRzIDwtIGx5cmljX2JpZ3JhbXMgJT4lCiAgICAgIHNlcGFyYXRlKGJpZ3JhbSwgYygid29yZDEiLCAid29yZDIiKSwgc2VwID0gIiAiKSAlPiUKICAgICAgY291bnQod29yZDEsIHdvcmQyLCBzb3J0ID0gVFJVRSkKICAgIGNvbWJpbmVkX3dvcmRzIDwtIGFwcGx5KGJpZ3JhbV9jb3VudHNbYygxLCAyKV0sIDEsIHBhc3RlICwgY29sbGFwc2UgPSAiICIgKVsxOmlucHV0JHRvcEJpZ3JhbXNdCiAgICB4X25hbWVzIDwtIGZhY3Rvcihjb21iaW5lZF93b3JkcywgbGV2ZWxzID0gcmV2KGNvbWJpbmVkX3dvcmRzKSkKICAgIHBsb3RfbHkoCiAgICAgIHggPSBiaWdyYW1fY291bnRzJG5bMTppbnB1dCR0b3BCaWdyYW1zXSwKICAgICAgeSA9IHhfbmFtZXMsCiAgICAgIG5hbWUgPSAiQmlncmFtIiwKICAgICAgdHlwZSA9ICJiYXIiLAogICAgICBvcmllbnRhdGlvbiA9ICdoJwogICAgKQogIH0pCiAgb3V0cHV0JGJpZ3JhbTIgPC0gcmVuZGVyUGxvdGx5KHsKICAgIHllYXJfc3RhcnQgPC0gYXMuaW50ZWdlcihzdWJzdHIoaW5wdXQkZGVjYWRlMiwgMSwgNCkpCiAgICBkdF9zdWIgPC0gZmlsdGVyKGR0X2x5cmljc18yLCB5ZWFyPj15ZWFyX3N0YXJ0KSAlPiUKICAgICAgZmlsdGVyKHllYXI8KHllYXJfc3RhcnQrMTApKQogICAgbHlyaWNfYmlncmFtcyA8LSBkdF9zdWIgJT4lCiAgICAgIHVubmVzdF90b2tlbnMoYmlncmFtLCBzdGVtbWVkd29yZHMsIHRva2VuID0gIm5ncmFtcyIsIG4gPSAyKQogICAgYmlncmFtX2NvdW50cyA8LSBseXJpY19iaWdyYW1zICU+JQogICAgICBzZXBhcmF0ZShiaWdyYW0sIGMoIndvcmQxIiwgIndvcmQyIiksIHNlcCA9ICIgIikgJT4lCiAgICAgIGNvdW50KHdvcmQxLCB3b3JkMiwgc29ydCA9IFRSVUUpCiAgICBjb21iaW5lZF93b3JkcyA8LSBhcHBseShiaWdyYW1fY291bnRzW2MoMSwgMildLCAxLCBwYXN0ZSAsIGNvbGxhcHNlID0gIiAiIClbMTppbnB1dCR0b3BCaWdyYW1zXQogICAgeF9uYW1lcyA8LSBmYWN0b3IoY29tYmluZWRfd29yZHMsIGxldmVscyA9IHJldihjb21iaW5lZF93b3JkcykpCiAgICBwbG90X2x5KAogICAgICB4ID0gYmlncmFtX2NvdW50cyRuWzE6aW5wdXQkdG9wQmlncmFtc10sCiAgICAgIHkgPSB4X25hbWVzLAogICAgICBuYW1lID0gIkJpZ3JhbSIsCiAgICAgIHR5cGUgPSAiYmFyIiwKICAgICAgb3JpZW50YXRpb24gPSAnaCcKICAgICkKICB9KQogIG91dHB1dCR0YWJsZSA8LSBEVDo6cmVuZGVyRGF0YVRhYmxlKHsKICAgIERUOjpkYXRhdGFibGUoZHRfbHlyaWNzXzIpCiAgfSkKfQpgYGAKCgpgYGB7ciBzaGlueSBhcHBfMSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3IgPSBGQUxTRX0KIyMjIFJ1biB0aGUgUiBTaGlueSBhcHAKCnNoaW55QXBwKHVpLCBzZXJ2ZXIpCmBgYAoKSG93IG1hbnkgc29uZ3MgYXJlIGluIGVhY2ggZ2VucmU/CmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpjb3VudHMgPC0gdGFibGUoZHRfbHlyaWNzXzFfYSRnZW5yZSkKYmFycGxvdChjb3VudHMsIG1haW4gPSAiIyBzb25ncyBieSBnZW5yZSIsIHhsYWIgPSAiZ2VucmUiLCB5bGFiID0gIiMgc29uZ3MiLCBjb2wgPSAiYmx1ZSIpCmBgYAoKCgpMZXQncyBzZXBhcmF0ZSBlYWNoIHNvbmcgaW50byBpbmRpdmlkdWFsIGx5cmljcyB1c2luZyBvdXIgb3JpZ2luYWwsIGZ1bGwgc2V0IG9mIGx5cmljcyAoaW5jbHVkaW5nIHdvcmRzIGxpa2UgImxvdmUiKS4gV2hhdCBhcmUgdGhlIG1vc3QgY29tbW9uIHdvcmRzIGFjcm9zcyB0aGUgZW50aXJlIGRhdGFzZXQ/CmBgYHtyLCB3YXJuaW5nPUZBTFNFLGVycm9yPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRX0KbHlyaWNzX3dvcmRzX2FsbCA8LSBkdF9seXJpY3NfMV9hICU+JQogIHVubmVzdF90b2tlbnMod29yZCxzdGVtbWVkd29yZHMpCgp0aWR5X2x5cmljc18xX2E8LSBseXJpY3Nfd29yZHNfYWxsICU+JQogIGNvdW50KHdvcmQsIHNvcnQgPSBUUlVFKQpgYGAKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLGVycm9yPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CnRpZHlfbHlyaWNzXzFfYSAlPiUKICBhcnJhbmdlKGRlc2MobikpICU+JQogIG11dGF0ZSh3b3JkID0gZmFjdG9yKHdvcmQsIGxldmVscyA9IHJldih1bmlxdWUod29yZCkpKSkgJT4lIAogIHRvcF9uKDI1KSAlPiUgCiAgZ2dwbG90KGFlcyh3b3JkLCBuLCBmaWxsPSJncmVlbiIpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGxhYnMoeCA9ICJtb3N0IGNvbW1vbiB3b3JkcyIsIHkgPSAibnVtYmVyIG9mIG9jY3VyZW5jZXMgaW4gZGF0YXNldCAiKSArCiAgZ2d0aXRsZSgiTW9zdCBjb21tb24gd29yZHMgYWNyb3NzIGRhdGFzZXQiKSArCiAgY29vcmRfZmxpcCgpCgpgYGAKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBlY2hvID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMjI2NyZWF0ZSBzZXQgb2YgbHlyaWNzIGRpdmlkZWQgYnkgZ2VucmUKdGlkeV9seXJpY3MgPC0gZHRfbHlyaWNzXzFfYSAlPiUKICB1bm5lc3RfdG9rZW5zKHdvcmQsc3RlbW1lZHdvcmRzKQoKbHlyaWNzX3dvcmRzX2dlbnJlIDwtIHRpZHlfbHlyaWNzICU+JQogIGNvdW50KHdvcmQsIGdlbnJlLCBzb3J0ID0gVFJVRSkgCmBgYAoKCk5vdywgd2UgY2FuIHNlZSB0cmVuZHMgaW4gdGhlIGRhdGEhCgpMb3ZlIGlzIHRoZSBtb3N0IGNvbW1vbiB3b3JkIGluIGV2ZXJ5IGdlbnJlIGV4Y2VwdCBNZXRhbCAod2hlcmUgaXQgc3RpbGwgcmFua3MgaGlnaGx5LCBidXQgaXMgZWNsaXBzZWQgYnkgInRpbWUiIGFuZCAibGlmZSIpLiBJbiBIaXAtSG9wLCAibG92ZSIgaXMgY2xvc2VseSBmb2xsb3dlZCBpbiBjb3VudHMgYnkgInNoaXQiICh3aGljaCBpcyB1bmlxdWVseSBoaWdoLXJhbmtpbmcgaW4gSGlwLUhvcCkuIAoKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojZ3JhcGhpbmcgY29kZXMgZnJvbSBodHRwczovL3d3dy50aWR5dGV4dG1pbmluZy5jb20vdGZpZGYuaHRtbAojc2VwYXJhdGUgd29yZHMgYnkgZ2VucmUgZ3JhcGhpY2FsbHkKCmx5cmljc193b3Jkc19nZW5yZSAlPiUKICBhcnJhbmdlKGRlc2MobikpICU+JQogIG11dGF0ZSh3b3JkID0gZmFjdG9yKHdvcmQsIGxldmVscyA9IHJldih1bmlxdWUod29yZCkpKSkgJT4lIAogIGdyb3VwX2J5KGdlbnJlKSAlPiUgCiAgdG9wX24oMTIpICU+JSAKICB1bmdyb3VwKCkgJT4lCiAgZ2dwbG90KGFlcyh3b3JkLCBuLCBmaWxsID0gZ2VucmUpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGxhYnMoeCA9ICJtb3N0IGNvbW1vbiB3b3JkcyIsIHkgPSAibnVtYmVyIG9mIG9jY3VyZW5jZXMgaW4gZ2VucmUgIikgKwogIGZhY2V0X3dyYXAofmdlbnJlLCBuY29sID0gMiwgc2NhbGVzID0gImZyZWUiKSArCiAgY29vcmRfZmxpcCgpCgpgYGAKCkxldCdzIHRha2UgYSBjbG9zZXIgbG9vayBhdCBiaWdyYW1zLiBXaGljaCBhcmUgdGhlIG1vc3QgY29tbW9uPwpgYGB7ciwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0KI2Fzc2lnbiBiaWdyYW1zCmx5cmljX2JpZ3JhbXMgPC0gZHRfbHlyaWNzXzFfYSAlPiUKICB1bm5lc3RfdG9rZW5zKGJpZ3JhbSwgc3RlbW1lZHdvcmRzLCB0b2tlbiA9ICJuZ3JhbXMiLCBuID0gMikKbHlyaWNfYmlncmFtcyA8LSBseXJpY19iaWdyYW1zWyAsIGMoNCwgNyldCgojY291bnQgYmlncmFtcyBpbnRvIHdvcmRzIGZvciBsYXRlciB1c2UKYmlncmFtcyA8LSBseXJpY19iaWdyYW1zICU+JQogIHNlcGFyYXRlKGJpZ3JhbSwgYygid29yZDEiLCAid29yZDIiKSwgc2VwID0gIiAiKQoKYmlncmFtX2NvdW50IDwtIGNvdW50KGJpZ3JhbXMsd29yZDEsIHdvcmQyLCBzb3J0ID0gVFJVRSkKCmJpZ3JhbXMgPC0gdW5pdGUoYmlncmFtcywgYmlncmFtLCBjKHdvcmQxLCB3b3JkMiksIHNlcCA9ICIgIiwgcmVtb3ZlID0gRkFMU0UpCiNiaWdyYW1zIDwtIGJpZ3JhbXNbICxjKDQsIDcsIDgsIDkpXQpgYGAKCmBgYHtyLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgZXJyb3IgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQojbG9vayBhdCBiaWdyYW0gY291bnRzIGJ5IGdlbnJlCmJpZ3JhbV9jb3VudHNfZ2VucmUgIDwtIGx5cmljX2JpZ3JhbXMgJT4lCiAgY291bnQoYmlncmFtLCBnZW5yZSwgc29ydCA9IFRSVUUpCmBgYAoKYGBge3IsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQojIGxvb2sgYXQgbW9zdCBjb21tb24gYmlncmFtcyBieSBnZW5yZQpiaWdyYW1fY291bnRzX2dlbnJlICU+JQogIGFycmFuZ2UoZGVzYyhuKSkgJT4lCiAgbXV0YXRlKHdvcmQgPSBmYWN0b3IoYmlncmFtLCBsZXZlbHMgPSByZXYodW5pcXVlKGJpZ3JhbSkpKSkgJT4lIAogIGdyb3VwX2J5KGdlbnJlKSAlPiUgCiAgdG9wX24oMTIpICU+JSAKICB1bmdyb3VwKCkgJT4lCiAgZ2dwbG90KGFlcyh3b3JkLCBuLCBmaWxsID0gZ2VucmUpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGxhYnMoeCA9ICJtb3N0IGNvbW1vbiBiaWdyYW1zIiwgeSA9ICJudW1iZXIgb2Ygb2NjdXJlbmNlcyBpbiBnZW5yZSAiKSArCiAgZ2d0aXRsZSgiTW9zdCBjb21tb24gYmlncmFtcyBieSBnZW5yZSIpICsKICBmYWNldF93cmFwKH5nZW5yZSwgbmNvbCA9IDIsIHNjYWxlcyA9ICJmcmVlIikgKwogIGNvb3JkX2ZsaXAoKQpgYGAKCkxldCdzIHNlZSB3aGF0IHBlcmNlbnRhZ2Ugb2YgZWFjaCBnZW5yZSBpcyByZXByZXNlbnRlZCBieSB0aGUgbHlyaWMgImhvbWUiOgpgYGB7ciwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CiNzYXZlIGZvciBhbGwgY2FsY3VsYXRpb25zOyAjIGJpZ3JhbXMgdG90YWwgYnkgZ2VucmUKYmlncmFtX2NvdW50cyA8LSB0YWJsZShseXJpY19iaWdyYW1zJGdlbnJlKQoKI2hvbWUKbHlyaWNfYmlncmFtc19ob21lIDwtIGZpbHRlcihiaWdyYW1zLCgod29yZDEgPT0gImhvbWUiKXwod29yZDIgPT0gImhvbWUiKSkpCmJpZ3JhbV9jb3VudHNfaG9tZSA8LSB0YWJsZShseXJpY19iaWdyYW1zX2hvbWUkZ2VucmUpCmJhcnBsb3QoYmlncmFtX2NvdW50c19ob21lL2JpZ3JhbV9jb3VudHMsIG1haW4gPSAicGVyY2VudGFnZSBob21lIGNvdW50cyBieSBnZW5yZSIsIHhsYWIgPSAiZ2VucmUiLCB5bGFiID0gIiUgbHlyaWNzIiwgY29sID0gImJsdWUiKQpgYGAKCldlIHNlZSB0aGF0IEluZGllLCBDb3VudHJ5LCBhbmQgUiZCIGhhdmUgdGhlIGhpZ2hlc3QgcGVyY2VudGFnZSBvZiAiaG9tZSIgYmlncmFtcywgZm9sbG93ZWQgYnkgRm9saywgSmF6eiwgYW5kIFJvY2suIEhvbWUgaXMgYSBjb25jZXB0IHRoYXQgY2FuIGJlIHRpZWQgdG8gaGF2aW5nIGEgcGxhY2Ugb2Ygb25lJ3Mgb3duLCBvZnRlbiBmcm9tIGEgY29tZm9ydCBzdGFuZHBvaW50LiBDb3VsZCB0aGlzIGJlIGEgcmVmbGVjdGlvbiBvZiB0cnlpbmcgdG8gcmVzb25hdGUgd2l0aCBhIGN1bHR1cmUgdmFsdWluZyBjb21taXRtZW50IGFuZCBjb21mb3J0PwoKSG93IGFib3V0ICJkcmVhbSI/CmBgYHtyLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KbHlyaWNfYmlncmFtc19kcmVhbSA8LSBmaWx0ZXIoYmlncmFtcywoKHdvcmQxID09ICJkcmVhbSIpfCh3b3JkMiA9PSAiZHJlYW0iKSkpCgpiaWdyYW1fY291bnRzX2RyZWFtIDwtIHRhYmxlKGx5cmljX2JpZ3JhbXNfZHJlYW0kZ2VucmUpCmJhcnBsb3QoYmlncmFtX2NvdW50c19kcmVhbS9iaWdyYW1fY291bnRzLCBtYWluID0gInBlcmNlbnRhZ2UgZHJlYW0gY291bnRzIGJ5IGdlbnJlIiwgeGxhYiA9ICJnZW5yZSIsIHlsYWIgPSAiJSBseXJpY3MiLCBjb2wgPSAiYmx1ZSIpCmBgYApIZXJlIHRoZSBjbGVhciBzdGFuZG91dHMgYXJlIEphenogd2l0aCBvdmVyIDEuNCUgb2YgYmlncmFtcyBpbmNsdWRpbmcgImRyZWFtIiwgYW5kIEhpcC1Ib3Agd2hpY2ggbWVudGlvbnMgImRyZWFtIiBsZXNzIGZyZXF1ZW50bHkgdGhhbiBKYXp6IGRvZXMgYnkgYSBmYWN0b3Igb2YgNyEgImRyZWFtIiBjYW4gYmUgY29ubmVjdGVkIHRvIGFic3RyYWN0IChhcyBvcHBvc2VkIHRvIGNvbmNyZXRlKSBnb2FscyBvciBlcGlzb2RlcyB0aGF0IG9jY3VyIG91dHNpZGUgcmVhbGl0eS4gQ291bGQgaXQgYmUgdGhhdCBKYXp6IGlzIG1vcmUgYWJvdXQgaW1hZ2luYXRpb24gYW5kIHRoZSBoeXBvdGhldGljYWwsIHdoaWxlIEhpcC1Ib3AgaXMgbW9yZSBhYm91dCB0aGUgcmVhbCBhbmQgY29uY3JldGU/CgpMZXQncyBzZWUgImRheSIgYW5kICJuaWdodCIgYXMgYSBjb21wYXJpc29uOgpgYGB7ciwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CiNkYXkKbHlyaWNfYmlncmFtc19kYXkgPC0gZmlsdGVyKGJpZ3JhbXMsKCh3b3JkMSA9PSAiZGF5Iil8KHdvcmQyID09ICJkYXkiKSkpCmJpZ3JhbV9jb3VudHNfZGF5IDwtIHRhYmxlKGx5cmljX2JpZ3JhbXNfZGF5JGdlbnJlKQoKI25pZ2h0Cmx5cmljX2JpZ3JhbXNfbmlnaHQgPC0gZmlsdGVyKGJpZ3JhbXMsKCh3b3JkMSA9PSAibmlnaHQiKXwod29yZDIgPT0gIm5pZ2h0IikpKQpiaWdyYW1fY291bnRzX25pZ2h0IDwtIHRhYmxlKGx5cmljX2JpZ3JhbXNfbmlnaHQkZ2VucmUpCgpgYGAKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLGVycm9yPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CiNncmFwaCBkYXkgdiBuaWdodApkZl90ZW1wb3JhbCA8LSByYmluZChiaWdyYW1fY291bnRzX2RheS9iaWdyYW1fY291bnRzLCBiaWdyYW1fY291bnRzX25pZ2h0L2JpZ3JhbV9jb3VudHMpCmJhcnBsb3QoZGZfdGVtcG9yYWwsIG1haW4gPSAicGVyY2VudGFnZSBkYXkgdnMgbmlnaHQgY291bnRzIGJ5IGdlbnJlIiwgeGxhYiA9ICJnZW5yZSIsIHlsYWIgPSAiJSBseXJpY3MiLCBjb2w9YygibGlnaHRibHVlIiwiZGFya2JsdWUiKSwgbGVnZW5kID0gYygiZGF5IiwgIm5pZ2h0IiksIGJlc2lkZSA9IFRSVUUpCmBgYAoKV2UgY2FuIHNlZSB0aGF0ICJkYXkiIGlzIGEgbW9yZSBmcmVxdWVudCB0aGVtZSB0aGFuICJuaWdodCIgaW4gYWxsIGdlbnJlcyBpbiB0aGlzIGRhdGFzZXQsIHdpdGggdGhlIGV4Y2VwdGlvbiBvZiBFbGVjdHJvbmljLiBFbGVjdHJvbmljIG11c2ljIGlzIG9mdGVuIGxpc3RlbmVkIHRvIGF0IG5pZ2h0LCBpbiBkYXJrIHNwYWNlcyB3aGVyZSBsaXN0ZW5lcnMgYXJlIGVxdWlwcGVkIHdpdGggZmx1b3Jlc2NlbnQgYWNjZXNzb3JpZXMuICBUaGlzIGlzIG9uZSBoeXBvdGhlc2lzIGFzIHRvIHdoeSBFbGVjdHJvbmljIG11c2ljIGV4cGxpY2l0bHkgbWVudGlvbnMgbmlnaHQgbW9yZSBmcmVxdWVudGx5IHRoYW4gZGF5LgoKSG93IGFib3V0IGdlbmRlcmVkIHdvcmRzPyBMZXQncyBsb29rIHNwZWNpZmljYWxseSBhdCAiYm95IiB2cyAiZ2lybCI6CmBgYHtyLCB3YXJuaW5nPUZBTFNFLGVycm9yPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CiNib3kKbHlyaWNfYmlncmFtc19ib3kgPC0gZmlsdGVyKGJpZ3JhbXMsKCh3b3JkMSA9PSAiYm95Iil8KHdvcmQyID09ICJib3kiKSkpCmJpZ3JhbV9jb3VudHNfYm95IDwtIHRhYmxlKGx5cmljX2JpZ3JhbXNfYm95JGdlbnJlKQoKI2dpcmwKbHlyaWNfYmlncmFtc19naXJsIDwtIGZpbHRlcihiaWdyYW1zLCgod29yZDEgPT0gImdpcmwiKXwod29yZDIgPT0gImdpcmwiKSkpCmJpZ3JhbV9jb3VudHNfZ2lybCA8LSB0YWJsZShseXJpY19iaWdyYW1zX2dpcmwkZ2VucmUpCmBgYAoKYGBge3IsIHdhcm5pbmc9RkFMU0UsZXJyb3I9RkFMU0UsbWVzc2FnZT1GQUxTRX0KI2dyYXBoIGJveSB2IGdpcmwKZGZfZ2VuZGVyIDwtIHJiaW5kKGJpZ3JhbV9jb3VudHNfYm95L2JpZ3JhbV9jb3VudHMsIGJpZ3JhbV9jb3VudHNfZ2lybC9iaWdyYW1fY291bnRzKQpiYXJwbG90KGRmX2dlbmRlciwgbWFpbiA9ICJwZXJjZW50YWdlIGJveSB2cyBnaXJsIGNvdW50cyBieSBnZW5yZSIsIHhsYWIgPSAiZ2VucmUiLCB5bGFiID0gIiUgbHlyaWNzIiwgY29sPWMoImJsYWNrIiwicmVkIiksIGxlZ2VuZCA9IGMoImJveSIsICJnaXJsIiksIGJlc2lkZSA9IFRSVUUpCmBgYApUaGlzIGlzIHRoZSBtb3N0IHN0YXJrIGNvbXBhcmlzb24geWV0IC0gaXQgc2VlbXMgdGhhdCBpbiBhbGwgZ2VucmVzLCAiZ2lybCIgaXMgbWVudGlvbmVkIG1vcmUgZXhwbGljdGx5IHRoYW4gImJveSIsIGFuZCBpbiB0aGUgY2FzZSBvZiBIaXAtSG9wLCBQb3AsIGFuZCBSJkIsICJnaXJsIiBpcyBtZW50aW9uZWQgbW9yZSB0aGFuIDJ4IGFzIGZyZXF1ZW50bHkgYXMgImJveSIhCgpGb3IgZnVuLCBsZXQncyB0aHJvdyAibG92ZSIiIGluIHRoZSBtaXg6CgpgYGB7ciwgd2FybmluZz1GQUxTRSxlcnJvcj1GQUxTRSxtZXNzYWdlPUZBTFNFfQojbG92ZQpseXJpY19iaWdyYW1zX2xvdmUgPC0gZmlsdGVyKGJpZ3JhbXMsKCh3b3JkMSA9PSAibG92ZSIpfCh3b3JkMiA9PSAibG92ZSIpKSkKYmlncmFtX2NvdW50c19sb3ZlIDwtIHRhYmxlKGx5cmljX2JpZ3JhbXNfbG92ZSRnZW5yZSkKCgojZ3JhcGggYm95IHYgZ2lybCB2IGxvdmUKZGZfZ2VuZGVyX2xvdmUgPC1yYmluZChiaWdyYW1fY291bnRzX2JveS9iaWdyYW1fY291bnRzLCBiaWdyYW1fY291bnRzX2dpcmwvYmlncmFtX2NvdW50cywgYmlncmFtX2NvdW50c19sb3ZlL2JpZ3JhbV9jb3VudHMpCmJhcnBsb3QoZGZfZ2VuZGVyX2xvdmUsIG1haW4gPSAicGVyY2VudGFnZSBib3kgdnMgZ2lybCB2cyBsb3ZlIGNvdW50cyBieSBnZW5yZSIsIHhsYWIgPSAiZ2VucmUiLCB5bGFiID0gIiUgbHlyaWNzIiwgY29sPWMoImJsYWNrIiwicmVkIiwgInB1cnBsZSIpLCBsZWdlbmQgPSBjKCJib3kiLCAiZ2lybCIsICJsb3ZlIiksIGJlc2lkZSA9IFRSVUUpCmBgYApXZSBjYW4gc2VlIHRoYXQgSGlwLUhvcCBoYXMgdGhlIHNtYWxsZXN0IGdhcCBiZXR3ZWVuIGNvdW50cyBvZiAibG92ZSIgYW5kICJnaXJsIiwgYW5kIHRoYXQgSmF6eiBoYXMgYW4gdW51c3VhbGx5IGhpZ2ggZ2FwIGJldHdlZW4gImxvdmUiIGFuZCAiZ2lybCIgY29tcGFyZWQgdG8gb3RoZXIgZ2VucmVzLiBUaGlzIGlzIGluIGxpbmUgd2l0aCB0aGUgaHlwb3RoZXNpcyB0aGF0IGltYWdpbmF0aW9uIG9yIGFuIGV0aGVyZWFsIHN0YXRlIGlzIG1vcmUgYXNzb2NpYXRlZCB3aXRoIEphenosIGFuZCByZWFsaXR5L2NvbmNyZXRlbmVzcyB3aXRoIEhpcC1Ib3A6IGdpcmxzIGFyZSBvYmplY3RpdmVseSB0YW5naWJsZSwgd2hpbGUgbG92ZSBpcyBub3QuIAoKTGV0J3MgZG8gYSBzZW50aW1lbnQgYW5hbHlzaXMgdG8gc2VlIGhvdyBuZWdhdGl2ZSBvciBwb3NpdGl2ZSBlYWNoIGdlbnJlIGlzOgpgYGB7ciwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSxlcnJvcj1GQUxTRSxtZXNzYWdlPUZBTFNFfQojIENvZGUgZnJvbSBodHRwczovL3BhbGRob3VzLmdpdGh1Yi5pby9OSUNBUi8yMDE5L3ItdGV4dC1hbmFseXNpcy5odG1sCiMgbG9hZCBsZXhpY29uIGZyb20gaHR0cHM6Ly93d3cuY3MudWljLmVkdS9+bGl1Yi9GQlMvc2VudGltZW50LWFuYWx5c2lzLmh0bWwKYmluZyA8LSBnZXRfc2VudGltZW50cygiYmluZyIpCgojIGpvaW4gc2VudGltZW50cwpzZW50aW1lbnRzIDwtIGx5cmljc193b3Jkc19hbGwgJT4lCiAgaW5uZXJfam9pbihiaW5nLCBieSA9ICJ3b3JkIikgIyU+JQoKc2VudGltZW50c19jb3VudHMgPC0gc2VudGltZW50cyAlPiUKICBncm91cF9ieShnZW5yZSkgJT4lCiAgY291bnQoc2VudGltZW50KSAlPiUKICBhcnJhbmdlKC1uKQoKbmVnYXRpdmVfZnJlcXMgPC0gc2VudGltZW50c19jb3VudHMgJT4lCiAgbGVmdF9qb2luKHNlbnRpbWVudHNfY291bnRzICU+JSAKICAgICAgICAgICAgICBncm91cF9ieShnZW5yZSkgJT4lIAogICAgICAgICAgICAgIHN1bW1hcmlzZSh0b3RhbCA9IHN1bShuKSkpICU+JQogIG11dGF0ZShwZXJjZW50ID0gcm91bmQobi90b3RhbCoxMDAsMikpICU+JQogIGZpbHRlcihzZW50aW1lbnQgPT0gIm5lZ2F0aXZlIikKCm5lZ2F0aXZlX2ZyZXFzCmBgYAoKYGBge3Isd2FybmluZz1GQUxTRSxlcnJvcj1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CnBvc2l0aXZlX2ZyZXFzIDwtIHNlbnRpbWVudHNfY291bnRzICU+JQogIGxlZnRfam9pbihzZW50aW1lbnRzX2NvdW50cyAlPiUgCiAgICAgICAgICAgICAgZ3JvdXBfYnkoZ2VucmUpICU+JSAKICAgICAgICAgICAgICBzdW1tYXJpc2UodG90YWwgPSBzdW0obikpKSAlPiUKICBtdXRhdGUocGVyY2VudCA9IHJvdW5kKG4vdG90YWwqMTAwLDIpKSAlPiUKICBmaWx0ZXIoc2VudGltZW50ID09ICJwb3NpdGl2ZSIpCgpwb3NpdGl2ZV9mcmVxcwpgYGAKV2Ugc2VlIHRoYXQgdGhlIG1vc3QgcG9zaXRpdmUgZ2VucmVzICh1c2luZyB0aGUgYmluZyBzZW50aW1lbnQgZGF0YWJhc2UpIGFyZSBKYXp6IChvdXIgcG90ZW50aWFsbHkgaW1hZ2luaXRpdmUgYW5kIGFic3RyYWN0IGdlbnJlKSwgUiZCLCBQb3AsIGFuZCBDb3VudHJ5LiBUaGUgbW9zdCBuZWdhdGl2ZSBhcmUgTWV0YWwgKHNlZSB0aGUgd29yZCBjbG91ZHMgZnJvbSBlYXJsaWVyIC0gdGhhdCdzIGEgbG90IG9mIGRlYXRoISkgYW5kIEhpcC1Ib3AgKG91ciBwb3RlbnRpYWxseSByZWFsaXN0IGNhdGVnb3J5KS4KYGBge3IsIHdhcm5pbmc9RkFMU0UsZXJyb3I9RkFMU0UsbWVzc2FnZT1GQUxTRX0KcG9zaXRpdmVfZnJlcXMgJT4lCiAgYXJyYW5nZShkZXNjKHBlcmNlbnQpKSAlPiUKICBtdXRhdGUod29yZCA9IGZhY3RvcihnZW5yZSwgbGV2ZWxzID0gcmV2KHVuaXF1ZShnZW5yZSkpKSkgJT4lIAogICN0b3BfbigyNSkgJT4lIAogIGdncGxvdChhZXMoZ2VucmUsIHBlcmNlbnQsIGNvbG9yPSJibHVlIikpICsKICBnZW9tX2NvbChzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgbGFicyh4ID0gImdlbnJlIiwgeSA9ICJwZXJjZW50IHBvc2l0aXZpdHkiKSArCiAgZ2d0aXRsZSgiSG93IHBvc2l0aXZlIGlzIHRoZSBnZW5yZT8iKSsKICBjb29yZF9mbGlwKCkKYGBgCgoKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLGVycm9yPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRX0KbnJjX3dvcmRfY291bnRzIDwtIGx5cmljc193b3Jkc19nZW5yZSAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJucmMiKSkgJT4lCiAgY291bnQod29yZCwgc2VudGltZW50LCBzb3J0ID0gVFJVRSkgJT4lCiAgdW5ncm91cCgpCgpgYGAKV2hhdCBpcyB0aGUgYnJlYWtkb3duIG9mIHNlbnRpbWVudCBieSBnZW5yZT8gV2Ugc2VlIHRoYXQgc29tZSBnZW5yZXMgKEphenosIFImQikgaGF2ZSBhIG1vcmUgYmFsYW5jZWQgcG9zaXRpdmUgdiBuZWdhdGl2ZSBtZWFzdXJlLiBJbiBnZW5lcmFsLCBhIHN1cnByaXNpbmcgZmluZCBpcyB0aGF0IGFuZ2VyIGFuZCB0cnVzdCBzZWVtIHRvIG9jY3VyIGluIHJvdWdobHkgc2ltaWxhciBmcmVxdWVuY2llcyB3aXRoaW4gYSBnaXZlbiBnZW5yZS4KYGBge3IsIHdhcm5pbmc9RkFMU0UsZXJyb3I9RkFMU0UsbWVzc2FnZT1GQUxTRX0KI2NvZGUgYWRhcHRlZCBmcm9tIGh0dHBzOi8vd3d3LmRhdGFjYW1wLmNvbS9jb21tdW5pdHkvdHV0b3JpYWxzL3NlbnRpbWVudC1hbmFseXNpcy1SCm5yY193b3JkX2NvdW50cyAlPiUKICBncm91cF9ieShnZW5yZSkgJT4lCiAgdG9wX24oMTApICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoc2VudGltZW50ID0gcmVvcmRlcihzZW50aW1lbnQsIG5uKSkgJT4lCiAgI211dGF0ZSh3b3JkID0gcmVvcmRlcih3b3JkLCBubikpICU+JQogIGdncGxvdChhZXMoc2VudGltZW50LCBubiwgZmlsbCA9IGdlbnJlKSkgKwogIGdlb21fY29sKHNob3cubGVnZW5kID0gRkFMU0UpICsKICBmYWNldF93cmFwKH5nZW5yZSwgc2NhbGVzID0gImZyZWVfeSIpICsKICBsYWJzKHkgPSAic2VudGltZW50IiwKICAgICAgIHggPSAiIyBjb3VudHMgb2Ygc2VudGltZW50IikgKwogIGdndGl0bGUoIlNlbnRpbWVudCBCcmVha2Rvd24gYnkgR2VucmUiKSArCiAgY29vcmRfZmxpcCgpCmBgYAoKCgpSZWZlcmVuY2VzOgoKIkNoZW5nbGlhbmcgVGFuZywgQXJwaXRhIFNoYWgsIFl1amllIFdhbmcgYW5kIFRpYW4gWmhlbmciCiJseXJpY3NfZmlsdGVyLmNzdiIgaXMgYSBmaWx0ZXJlZCBjb3JwdXMgb2YgMzgwLDAwMCsgc29uZyBseXJpY3MgZnJvbSBmcm9tIE1ldHJvTHlyaWNzLiBZb3UgY2FuIHJlYWQgbW9yZSBhYm91dCBpdCBvbiBbS2FnZ2xlXShodHRwczovL3d3dy5rYWdnbGUuY29tL2d5YW5pOTUvMzgwMDAwLWx5cmljcy1mcm9tLW1ldHJvbHlyaWNzKS4KCiJpbmZvX2FydGlzdC5jc3YiIHByb3ZpZGVzIHRoZSBiYWNrZ3JvdW5kIGluZm9ybWF0aW9uIG9mIGFsbCB0aGUgYXJ0aXN0aXMuIFRoZXNlIGluZm9ybWF0aW9uIGFyZSBzY3JhcGVkIGZyb20gW0x5cmljc0ZyZWFrXShodHRwczovL3d3dy5seXJpY3NmcmVhay5jb20vKS4KClRoZSBzZW50aW1lbnQgYW5hbHlzaXMgbWFrZXMgdXNlIG9mIHRoZSBOUkMgRW1vdGlvbiBhbmQgU2VudGltZW50IEFuYWx5c2lzLCBjcmVhdGVkIGJ5IFNhaWYgTS4gTW9oYW1tYWQgYW5kIFBldGVyIEQuIFR1cm5leSBhdCB0aGUgTmF0aW9uYWwgUmVzZWFyY2ggQ291bmNpbCBDYW5hZGEuIGh0dHA6Ly9zYWlmbW9oYW1tYWQuY29tL1dlYlBhZ2VzL2xleGljb25zLmh0bWwKCkJpbmcgbGV4aWNvbiBmcm9tIGh0dHBzOi8vd3d3LmNzLnVpYy5lZHUvfmxpdWIvRkJTL3NlbnRpbWVudC1hbmFseXNpcy5odG1sCgpQaG90byBieSBTcGVuY2VyIEltYnJvY2sgb24gVW5zcGxhc2g6IGh0dHBzOi8vdW5zcGxhc2guY29tL3Bob3Rvcy9KQUhkUEhNb2FFQQoKQ29kZSBzbmlwcGV0cyBhZGFwdGVkIGZyb20gaHR0cHM6Ly9wYWxkaG91cy5naXRodWIuaW8vTklDQVIvMjAxOS9yLXRleHQtYW5hbHlzaXMuaHRtbCwgaHR0cHM6Ly93d3cudGlkeXRleHRtaW5pbmcuY29tLywgYW5kIGh0dHBzOi8vd3d3LmRhdGFjYW1wLmNvbS9jb21tdW5pdHkvdHV0b3JpYWxzL3NlbnRpbWVudC1hbmFseXNpcy1SCgoK